/*
 Copyright (C) 2009 are of bakabt
 boxtorrents, azureus, vuze, and java are copyrighted to their respective owner.

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; version 2 of the License.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 */
package com.boxtorrents.azureus;

import java.util.HashSet;
import java.util.Set;

import org.gudy.azureus2.plugins.Plugin;
import org.gudy.azureus2.plugins.PluginConfig;
import org.gudy.azureus2.plugins.PluginException;
import org.gudy.azureus2.plugins.PluginInterface;
import org.gudy.azureus2.plugins.download.DownloadAnnounceResult;
import org.gudy.azureus2.plugins.download.DownloadScrapeResult;
import org.gudy.azureus2.plugins.download.DownloadTrackerListener;
import org.gudy.azureus2.plugins.logging.LoggerChannel;
import org.gudy.azureus2.plugins.utils.LocaleUtilities;

import com.boxtorrents.azureus.action.TableCellRefresh;
import com.boxtorrents.azureus.action.ClientFilter;
import com.boxtorrents.azureus.action.NotificationAction;
import com.boxtorrents.azureus.action.PauseDownloadAction;
import com.boxtorrents.azureus.action.SerialDownload;
import com.boxtorrents.azureus.action.TrackerChangerAction;

/**
 * This azureus plugin meant to make <a
 * href="http://www.bakabt.com">boxtorrents</a> user can use boxtorrents
 * service easily. These process can be automated task or simply information
 * gathering.
 * 
 * @author are of bakabt
 * @version 0.1.5
 */
public class BoxTorrentsPlugin implements Plugin {
	// we don't expect multipe instance on one class loader
	// just make every field static
	private static LoggerChannel log = null;
	private static PluginInterface pi = null;
	private static PluginConfig pconfig = null;
	private static ConfigPage confPage = null;
	private static DataGatherer gatherer = null;
	private static boolean initialized = false;
	private static long lastCheck = 0;
	private static Set<StatCheckListener> checkListener = new HashSet<StatCheckListener>();

	/**
	 * @inheritDoc
	 */
	public void initialize(PluginInterface pluginInterface)
	    throws PluginException {
		if (initialized) throw new PluginException("Already initialized");
		pi = pluginInterface;
		log = pi.getLogger().getTimeStampedChannel("Boxtorrents");
		pconfig = pi.getPluginconfig();
		pi.getUIManager().createLoggingViewModel(log, false);
		// for this time, we only had one gatherer
		gatherer = new StatPageDataGatherer();

		// configuration page
		confPage = new ConfigPage();

		// adding listener on action
		checkListener.add(new NotificationAction());
		checkListener.add(new PauseDownloadAction());
		checkListener.add(new TableCellRefresh());
		checkListener.add(new TrackerChangerAction());
		new SerialDownload();
		new ClientFilter();

		initialized = true;

		// attach tracker announce on global download notifier
		pi.getDownloadManager().getGlobalDownloadEventNotifier()
		    .addTrackerListener(new DownloadTrackerListener() {
			    public void announceResult(DownloadAnnounceResult res) {
				    if (res == null
				        || res.getResponseType() == DownloadAnnounceResult.RT_ERROR)
				      return;

				    if (res.getURL() == null
				        || res.getURL().toExternalForm().indexOf(
				            "bakabt.com") < 0) return;
				    // one thread at one time, let's use internal sync method mechanism
				    doCheck();
			    }

			    public void scrapeResult(DownloadScrapeResult arg0) {}
		    }, true);
	}

	private synchronized void doCheck() {
		if (lastCheck == 0) forceCheck();
		else {
			int minDelay = pconfig.getPluginIntParameter("param.delay", 10);
			if (60000 * minDelay < System.currentTimeMillis() - lastCheck) {
				forceCheck();
			}
		}
	}

	/**
	 * Forcing {@link DataGatherer} to check
	 */
	public static synchronized void forceCheck() {
		lastCheck = System.currentTimeMillis();
		pi.getUtilities().createThread("check", new Runnable() {
			public void run() {
				log.log("[gatherer]starting to check");
				StatCheckEvent event = gatherer.doCheck();
				if (event != null) {
					confPage.recreateAssignMenu();
					for (StatCheckListener act : checkListener) {
						if (act.isEnabled()) act.onCheckResult(event);
					}
					log.log("[gatherer]finish");
				} else {
					lastCheck = -1;
					log.log("[gatherer]failed");
				}
			}
		});
	}

	/**
	 * @return the log
	 */
	public static LoggerChannel getLog() {
		return log;
	}

	/**
	 * @return the pi
	 */
	public static PluginInterface getPluginInterface() {
		return pi;
	}

	/**
	 * @return the config page
	 */
	public static ConfigPage getConfPage() {
		return confPage;
	}

	/**
	 * @return the gatherer
	 */
	public static DataGatherer getGatherer() {
		return gatherer;
	}

	/**
	 * @return locale util
	 */
	public static LocaleUtilities getLocaleUtil() {
		return pi.getUtilities().getLocaleUtilities();
	}

	/**
	 * @return the checkListener
	 */
	public static Set<StatCheckListener> getCheckListener() {
		return checkListener;
	}
}
